package net.lab1024.sa.admin.module.business.category.service;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.config.SynthesisException;
import net.lab1024.sa.admin.constant.SynthesisConst;
import net.lab1024.sa.admin.module.business.category.domain.entity.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class PythonServiceClient {

    private final RestTemplate restTemplate;
    private final String pythonServiceUrl;
    private final ObjectMapper objectMapper;

    // 从配置文件中注入服务地址
    public PythonServiceClient(RestTemplate restTemplate,
                               @Value("${python.service.url:http://localhost:5000}") String pythonServiceUrl,
                               ObjectMapper objectMapper) {
        this.restTemplate = restTemplate;
        this.pythonServiceUrl = pythonServiceUrl;
        this.objectMapper = objectMapper;
    }

    private void configureRestTemplate(
            MappingJackson2HttpMessageConverter converter) {

        // 移除默认转换器
        restTemplate.getMessageConverters().removeIf(
                c -> c instanceof MappingJackson2HttpMessageConverter
        );

        // 添加自定义转换器
        restTemplate.getMessageConverters().add(converter);
    }

    public RetroResponse.RetroResult2 performRetrosynthesis(SynthesisRequest synthesisRequest) {
        final String logPrefix = StringUtils.repeat("\n", 2);
        log.info("{}=== 开始调用逆合成分析服务 ===", logPrefix);
        log.info("入参 SMILES: {} databaseName: {} modelName: {}",
                synthesisRequest.getSmiles(), synthesisRequest.getDatabaseName(), synthesisRequest.getModelName());

        String apiUrl = UriComponentsBuilder.fromHttpUrl(pythonServiceUrl)
                .path("/retrosynthesis2")
                .toUriString();

        try {
            // 准备请求
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<SynthesisRequest> entity = new HttpEntity<>(synthesisRequest, headers);

            // 发送请求并获取原始 JSON
            ResponseEntity<String> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

            // 检查响应状态
            if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
                String body = response.getBody();
                //String errorMessage = getErrorMessage(body, SynthesisConst.EXCEPTION_CODE);
                String errorMessage = getErrorMessage(body);
                //String errorCode = getErrorMessage(body, SynthesisConst.EXCEPTION_CODE);

                throw new SynthesisException(errorMessage);
            }

            // 获取原始 JSON
            String rawJson = response.getBody();
            log.info("Python服务原始响应: {}", rawJson);

            // 处理 NaN 值 - 更精确的替换
            String sanitizedJson = rawJson
                    .replaceAll(":\\s*NaN\\b", ": null") // 匹配单独的 NaN
                    .replaceAll(":\\s*Infinity\\b", ": null"); // 处理 Infinity

            // 修正 JSON 格式问题
            sanitizedJson = sanitizedJson
                    .replace("result_code:", "\"result_code\":")
                    .replace("data:", "\"data\":")
                    .replace("message:", "\"message\":")
                    .replace("\n", ""); // 移除换行符

            // 解析 JSON
            ObjectMapper mapper = new ObjectMapper();
            mapper.enable(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS);
            mapper.enable(DeserializationFeature.ACCEPT_FLOAT_AS_INT);

            // 解析整个响应
            RetroResponse fullResponse = mapper.readValue(sanitizedJson, RetroResponse.class);

            // 获取 data 部分
            RetroResponse.RetroResult2 result = fullResponse.getData();
            //result = handleRetroResult2(synthesisRequest.getPId(), result);

            log.info("逆合成分析成功，结果状态: {}", fullResponse.getResultCode());
            log.info("{}=== 服务调用结束 ===", logPrefix);

            return result;
        } catch (HttpClientErrorException e) {
            // 处理400错误
            String responseBody = e.getResponseBodyAsString();
            log.error("Python服务返回错误: HTTP {} - {}", e.getRawStatusCode(), e.getStatusText());
            log.error("错误详情: {}", responseBody);
            //throw new SynthesisException("Python服务错误: " + responseBody, e);
            throw new SynthesisException("Python服务错误: " + e.getMessage());
        } catch (Exception e) {
            log.error("调用Python服务失败: {}", e.getMessage(), e);
            //throw new SynthesisException("调用Python服务失败: " + e.getMessage(), e);
            throw new SynthesisException(e.getMessage());
        }
    }

    private String getErrorMessage(String json) {
        try {
            // 1. 创建 ObjectMapper 实例
            ObjectMapper mapper = new ObjectMapper();

            // 2. 解析 JSON 到自定义类
            ErrorResponse errorResponse = mapper.readValue(json, ErrorResponse.class);

            return errorResponse.getError();
        } catch (Exception e) {
            log.error("json字符串转对象异常", e);
            return "";
        }
    }

    private String getErrorMessage(String json, String key) {
        try {
            // 1. 创建 ObjectMapper 实例
            ObjectMapper mapper = new ObjectMapper();

            // 2. 解析 JSON 到自定义类
            ErrorResponse errorResponse = mapper.readValue(json, ErrorResponse.class);

            if (SynthesisConst.EXCEPTION_CODE.equals(key)) {
                // 3. 直接获取错误消息（Jackson 会自动处理 Unicode 转义）
                return String.valueOf(errorResponse.getResult_code());
            }

            if (SynthesisConst.EXCEPTION_MESSAGE.equals(key)) {
                return errorResponse.getError();
            }

            return "";
        } catch (Exception e) {
            log.error("json字符串转对象异常", e);
            return "";
        }
    }


    public RetroResult2 performRetrosynthesis_20250805(SynthesisRequest synthesisRequest) {
        final String logPrefix = StringUtils.repeat("\n", 2);
        log.info("{}=== 开始调用逆合成分析服务 ===", logPrefix);
        log.info("入参 SMILES: {} databaseName: {} modelName: {}",
                synthesisRequest.getSmiles(), synthesisRequest.getDatabaseName(), synthesisRequest.getModelName());


        String apiUrl = UriComponentsBuilder.fromHttpUrl(pythonServiceUrl)
                .path("/retrosynthesis2")
                .toUriString();

        try {
            String unicodeStr = "\u65e0\u6548\u7684SMILES\u683c\u5f0f";
            log.info(unicodeStr); // 输出: 无效的SMILES格式

            // 准备请求
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            String originalSmiles = synthesisRequest.getSmiles();
            log.info("原始 SMILES: {}", originalSmiles);

            // 仅清理空格，不改变化学结构
            String cleanedSmiles = cleanSmiles(originalSmiles);
            log.info("清理空格后 SMILES: {}", cleanedSmiles);

            // 验证但不修改结构
            //validateSmiles(cleanedSmiles);


            SynthesisRequest validatedRequest = new SynthesisRequest(
                    originalSmiles,
                    synthesisRequest.getDatabaseName(),
                    synthesisRequest.getModelName()
            );// 2. 打印清理后的 SMILES

            HttpEntity<SynthesisRequest> entity = new HttpEntity<>(validatedRequest, headers);

            // 发送请求并获取原始 JSON
            ResponseEntity<String> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

            // 检查响应状态
            if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
                throw new SynthesisException("无效响应状态: " + response.getStatusCode());
            }

            // 获取原始 JSON
            String rawJson = response.getBody();
            log.info("Python服务原始响应: {}", rawJson);

            // 处理 NaN 值
            String sanitizedJson = rawJson.replaceAll(":\\s*NaN", ": null");

            sanitizedJson = "{" + sanitizedJson + "}";
            // 解析 JSON
            RetroResult3 retroResult3 = objectMapper.readValue(sanitizedJson, RetroResult3.class);
            RetroResult2 result = retroResult3.getData();
            result = handleRetroResult2(synthesisRequest.getPId(), result);

            log.info("逆合成分析成功，返回结果");
            log.info("{}=== 服务调用结束 ===", logPrefix);

            return result;
        }

        //        catch (InvalidSmilesException e) {
        //            // 特殊处理 SMILES 格式错误
        //            log.error("无效的SMILES格式: {}", e.getMessage());
        //            throw new SynthesisException("无效的SMILES格式: " + e.getMessage(), e);
        //        }

        catch (HttpClientErrorException e) {
            // 处理400错误
            String responseBody = e.getResponseBodyAsString();
            log.error("Python服务返回错误: HTTP {} - {}", e.getRawStatusCode(), e.getStatusText());
            log.error("错误详情: {}", responseBody, e);

            throw new SynthesisException("生成失败");
        } catch (Exception e) {
            log.error("调用Python服务失败: {}", e.getMessage(), e);

            throw new SynthesisException("生成失败");
        }
    }


    private RetroResponse.RetroResult2 handleRetroResult2(String pId, RetroResponse.RetroResult2 retroResult2) {
        if (null == retroResult2)
            return null;
        if (StringUtils.isBlank(pId)) {
            return retroResult2;
        }
        List<RetroResponse.RetroResult2.Node> nodeList = retroResult2.getNodes();
        if (CollectionUtils.isNotEmpty(nodeList)) {
            for (RetroResponse.RetroResult2.Node node : nodeList) {
                String id = node.getId();
                id = pId.concat(":").concat(id);
                node.setId(id);
            }
        }

        List<RetroResponse.RetroResult2.Edge> edgeList = retroResult2.getEdges();
        if (CollectionUtils.isNotEmpty(edgeList)) {
            for (RetroResponse.RetroResult2.Edge edge : edgeList) {
                String source = edge.getSource();
                String target = edge.getTarget();
                source = pId.concat(SynthesisConst.COLON).concat(source);
                target = pId.concat(SynthesisConst.COLON).concat(target);
                edge.setSource(source);
                edge.setTarget(target);
            }
        }

        return retroResult2;
    }

    private RetroResult2 handleRetroResult2(String pId, RetroResult2 retroResult2) {
        if (null == retroResult2)
            return null;
        if (StringUtils.isBlank(pId)) {
            return retroResult2;
        }
        List<RetroResult2.Node> nodeList = retroResult2.getNodes();
        if (CollectionUtils.isEmpty(nodeList)) {
            return retroResult2;
        }
        for (RetroResult2.Node node : nodeList) {
            String id = node.getId();
            id = pId.concat(":").concat(id);
            node.setId(id);
        }
        return retroResult2;
    }


    // 仅清理空格，不改变化学结构
    private String cleanSmiles(String smiles) {
        return smiles.replaceAll("\\s+", "");
    }

    // 验证但不修改
    private void validateSmiles(String smiles) throws InvalidSmilesException {
        // 验证点号分隔符
        if (!smiles.matches("^([^.]+\\.)*[^.]+$")) {
            throw new InvalidSmilesException("无效的SMILES分隔符格式");
        }

        // 分割并验证每个SMILES
        String[] parts = smiles.split("\\.");
        for (String part : parts) {
            if (!isValidSmiles(part)) {
                throw new InvalidSmilesException("无效的SMILES格式: " + part);
            }
        }
    }

    // 自定义异常类
    public class InvalidSmilesException extends Exception {
        public InvalidSmilesException(String message) {
            super(message);
        }
    }

    // 修复环编号冲突
    private String fixRingNumbers(String smiles) {
        // 简单的修复：重新编号环
        Map<Character, Character> ringMap = new HashMap<>();
        char nextRing = '1';
        StringBuilder fixed = new StringBuilder();

        for (char c : smiles.toCharArray()) {
            if (Character.isDigit(c)) {
                if (!ringMap.containsKey(c)) {
                    ringMap.put(c, nextRing);
                    nextRing = (char) (nextRing + 1);
                    if (nextRing > '9') nextRing = '0';
                }
                fixed.append(ringMap.get(c));
            } else {
                fixed.append(c);
            }
        }

        return fixed.toString();
    }

    // SMILES 清理和验证方法
    private String cleanAndValidateSmiles(String smiles) {
        // 1. 去除所有空格
        String cleaned = smiles.replaceAll("\\s+", "");

        // 2. 验证点号分隔符
        if (!cleaned.matches("^([^.]+\\.)*[^.]+$")) {
            throw new SynthesisException("无效的SMILES分隔符格式");
        }

        // 3. 分割并验证每个SMILES
        String[] parts = cleaned.split("\\.");
        for (int i = 0; i < parts.length; i++) {
            if (!isValidSmiles(parts[i])) {
                throw new SynthesisException("无效的SMILES格式: " + parts[i]);
            }
        }

        return cleaned;
    }

    // 简单的SMILES格式验证
    private boolean isValidSmiles(String smiles) {
        // 基本规则：
        // 1. 至少4个字符
        // 2. 包含数字（表示环闭合）
        // 3. 合理的原子符号
        return smiles.length() >= 4 &&
                smiles.matches(".*\\d.*") &&
                smiles.matches("^[A-Za-z0-9=#@+\\-\\[\\]()\\\\/]+$");
    }


    public RetroResult2 performRetrosynthesis3(SynthesisRequest synthesisRequest) {
        log.info("{}=== log from performRetrosynthesis begin===", StringUtils.repeat("\n", 2));
        log.info("调用逆合成分析服务，入参 SMILES: {} databaseName: {} modelName: {}",
                synthesisRequest.getSmiles(), synthesisRequest.getDatabaseName(), synthesisRequest.getModelName());

        String apiUrl = UriComponentsBuilder.fromHttpUrl(pythonServiceUrl)
                .path("/retrosynthesis2")
                .toUriString();

        try {
            // 1. 发送请求获取原始JSON
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<SynthesisRequest> entity = new HttpEntity<>(synthesisRequest, headers);

            ResponseEntity<String> rawResponse = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

            // 2. 记录原始响应
            String rawJson = rawResponse.getBody();
            log.info("Python服务原始响应JSON: {}", rawJson);

            // 3. 处理NaN值并解析
            String sanitizedJson = rawJson.replaceAll(":\\s*NaN", ": null");
            RetroResult2 result = objectMapper.readValue(sanitizedJson, RetroResult2.class);

            //log.info("逆合成分析成功，结果摘要: routes={}", result.getRoutes());
            log.info("{}=== log from performRetrosynthesis end ===", StringUtils.repeat("\n", 2));

            return result;
        } catch (Exception e) {
            log.error("调用Python服务失败，SMILES: {}, 异常: {}",
                    synthesisRequest.getSmiles(), e.getMessage(), e);
            throw new SynthesisException("调用Python服务失败: " + e.getMessage(), e);
        }
    }

    // 移除冗余的 performRetrosynthesis2 方法
    // 移除 extractJsonFromResponse 方法


    public RetroResult2 performRetrosynthesis2(SynthesisRequest synthesisRequest) {
        // 打印入参（结构化日志）
        log.info(StringUtils.repeat("\n", 50) + "=== log from performRetrosynthesis begin===");
        log.info("调用逆合成分析服务，入参 SMILES: {} databaseName: {} modelName: {}", synthesisRequest.getSmiles(), synthesisRequest.getDatabaseName(), synthesisRequest.getModelName());

        String apiUrl = UriComponentsBuilder.fromHttpUrl(pythonServiceUrl)
                .path("/retrosynthesis2")
                .toUriString();
        log.debug("Python服务URL: {}", apiUrl); // 调试日志（生产环境可关闭）

        SynthesisRequest request = new SynthesisRequest(synthesisRequest.getSmiles(), synthesisRequest.getDatabaseName(), synthesisRequest.getModelName());
        log.debug("请求体: {}", request); // 需确保 SynthesisRequest 有合适的 toString()

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<SynthesisRequest> entity = new HttpEntity<>(request, headers);

        try {
            // 修改为获取原始JSON字符串
            ResponseEntity<String> rawResponse = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

            // 打印原始JSON响应
            String rawJson = rawResponse.getBody();
            log.info("Python服务原始响应JSON: {}", rawJson);

            // 直接映射到 RetroResult2 类
            ResponseEntity<RetroResult2> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    entity,
                    RetroResult2.class
            );

            // 打印原始响应状态码和响应体（可选）
            log.debug("Python服务响应状态码: {}", response.getStatusCode());
            log.debug("Python服务响应体: {}", response.getBody());

            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                RetroResult2 result = response.getBody();
                // 打印关键出参（避免日志过大，可选择性打印）
                log.info("逆合成分析成功，结果摘要: routes={}", result);
                endLog();
                return result;
            } else {
                String errorMsg = String.format("Python服务返回无效响应，状态码: %s", response.getStatusCode());
                log.error(errorMsg);
                endLog();
                throw new SynthesisException(errorMsg);
            }

        } catch (Exception e) {
            log.error("调用Python服务失败，SMILES: {}, 异常: {}", request.getSmiles(), e.getMessage(), e);
            endLog();
            throw new SynthesisException("调用Python服务失败: " + e.getMessage(), e);
        }
    }


    private void endLog() {
        log.info(StringUtils.repeat("\n", 50) + "=== log from performRetrosynthesis end ===");
    }

    /**
     * 调用 Python 微服务的逆合成分析接口
     *
     * @param smiles 目标分子的 SMILES 字符串
     * @return 逆合成分析结果
     */
    public RetroResult2 performRetrosynthesis2(String smiles) {
        // 构建请求 URL
        String apiUrl = UriComponentsBuilder.fromHttpUrl(pythonServiceUrl)
                .path("/retrosynthesis2")
                .toUriString();


        // 构建请求体
        SynthesisRequest request = new SynthesisRequest("", "", "");

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建 HTTP 实体
        HttpEntity<SynthesisRequest> entity = new HttpEntity<>(request, headers);

        try {
            // 1. 首先以字符串形式获取响应
            ResponseEntity<String> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

            // 检查响应状态
            if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
                throw new SynthesisException("Python 服务返回无效响应: " + response.getStatusCode());
            }

            String responseBody = response.getBody();

            // 2. 从响应中提取JSON部分
            String jsonContent = extractJsonFromResponse(responseBody);

            // 3. 手动解析JSON
            ObjectMapper mapper = new ObjectMapper();

            // 配置ObjectMapper处理特殊值（如NaN）
            mapper.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);

            RetroResult2 retroResult2 = mapper.readValue(jsonContent, RetroResult2.class);
            return retroResult2;
        } catch (Exception e) {
            throw new SynthesisException("调用 Python 服务失败: " + e.getMessage(), e);
        }
    }


    // 从包含TypeScript的响应中提取纯JSON内容
//    private String extractJsonFromResponse(String responseBody) {
//        // 查找JSON部分的开始位置
//        int startIndex = responseBody.indexOf("{\"nodes\":");
//        if (startIndex == -1) {
//            throw new SynthesisException("响应中未找到JSON数据");
//        }
//
//        // 查找JSON部分的结束位置
//        int braceCount = 0;
//        int endIndex = startIndex;
//        boolean inString = false;
//
//        for (int i = startIndex; i < responseBody.length(); i++) {
//            char c = responseBody.charAt(i);
//
//            if (c == '"' && (i == 0 || responseBody.charAt(i - 1) != '\\')) {
//                inString = !inString;
//            }
//
//            if (!inString) {
//                if (c == '{') braceCount++;
//                if (c == '}') braceCount--;
//
//                if (braceCount == 0) {
//                    endIndex = i + 1;
//                    break;
//                }
//            }
//        }
//
//        if (braceCount != 0) {
//            throw new SynthesisException("JSON结构不完整");
//        }
//
//        return responseBody.substring(startIndex, endIndex);
//    }

    private String extractJsonFromResponse(String responseBody) {
        // 1. 查找 nodeMock 赋值语句
        int startOfNodeMock = responseBody.indexOf("export const nodeMock =");
        if (startOfNodeMock == -1) {
            startOfNodeMock = responseBody.indexOf("const nodeMock =");
        }

        if (startOfNodeMock == -1) {
            throw new SynthesisException("响应中未找到 nodeMock 数据");
        }

        // 2. 定位到赋值语句后的第一个花括号
        int braceIndex = responseBody.indexOf('{', startOfNodeMock);
        if (braceIndex == -1) {
            throw new SynthesisException("未找到 JSON 起始大括号");
        }

        // 3. 从第一个花括号开始解析完整对象
        int braceCount = 0;
        boolean inString = false;
        boolean escapeNext = false;
        int endIndex = braceIndex;

        for (int i = braceIndex; i < responseBody.length(); i++) {
            char c = responseBody.charAt(i);

            if (escapeNext) {
                escapeNext = false;
                continue;
            }

            if (c == '\\') {
                escapeNext = true;
            } else if (c == '"') {
                inString = !inString;
            } else if (!inString) {
                if (c == '{') {
                    braceCount++;
                } else if (c == '}') {
                    braceCount--;
                    if (braceCount == 0) {
                        endIndex = i;
                        break;
                    }
                }
            }
        }

        if (braceCount != 0) {
            throw new SynthesisException("JSON 结构不完整，括号不匹配");
        }

        // 4. 返回完整JSON对象字符串
        return responseBody.substring(braceIndex, endIndex + 1);
    }
}